package com.neuedu.config;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.neuedu.entity.UmsDoctor;
import com.neuedu.entity.UmsUser;
import com.neuedu.util.HttpNeueduRequest;
import com.neuedu.util.JwtUtil;
import com.neuedu.vo.ResultJson;
import jakarta.annotation.Resource;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
@ConfigurationProperties(prefix = "ignore.white")
public class AuthorizationFilter implements Filter {

    List<String> urls ;
    @Value("${allow.origin}")
    String allowOrigin;
    @Resource(name = "wyRedisTemplate")
    RedisTemplate<String, Object> redisTemplate;
    @Resource
    ObjectMapper objectMapper;
    public void setUrls(List<String> urls) {
        this.urls = urls;
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        if (servletRequest instanceof HttpServletRequest request && servletResponse instanceof HttpServletResponse response) {
            // 如果前端向后端发请求的时候,如果请求头中有内容会先发一个OPTIONS请求，遇到OPTIONS请求直接通过
            if ("OPTIONS".equals(request.getMethod())) {
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            }
            // 创建地址匹配工具
            AntPathMatcher pathMatcher = new AntPathMatcher();
            // 循环白名单地址和当前请求地址一一匹配 如果有一个能匹配成功则通过
            for (String url : urls) {
                if (pathMatcher.match(url, request.getServletPath())) {
                    filterChain.doFilter(servletRequest, servletResponse);
                    return;
                }
            }
            // 获取token
            String token = request.getHeader("token");
            // 先校验有没有
            if (StringUtils.isBlank(token))  {
                // 如果token是空则返回401
                error(response, ResultJson.unauthorized("该用户未登录"));
                return;
            }
            UmsDoctor doctor = null;
            // 如果有token校验token是否正确
            try {
                doctor = JwtUtil.check(token);
            } catch (Exception e) {
                e.printStackTrace();
                error(response, ResultJson.unauthorized("非法请求"));
                return;
            }
           /* // 校验token是否超时
            String key = String.format("ums:%d:login", umsUser.getId());
            // 判断key是否存在
            if(!redisTemplate.hasKey(key)) {
                // 如果不存在表示超时
                error(response, ResultJson.unauthorized("登录已过期"));
                return;
            }
            // 如果key存在则延长超时时间
            redisTemplate.expire(key, 30, TimeUnit.MINUTES);*/
            // 创建一个新的request，将登录用户id保存到request参数列表中，为了方便controller可以直接获取到
            HttpNeueduRequest neueduRequest  = new HttpNeueduRequest(request);
            neueduRequest.addParams("open_id", String.valueOf(doctor.getId()));
            filterChain.doFilter(neueduRequest, response);
        } else {
            filterChain.doFilter(servletRequest, servletResponse);
        }
    }

    private void error (HttpServletResponse response, ResultJson resultJson) throws IOException {
        response.setHeader("Content-Type", "application/json;charset=utf-8");
        response.setHeader("Access-Control-Allow-Origin", allowOrigin);
        response.setHeader("Access-Control-Allow-Methods", "*");
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.getWriter().write(objectMapper.writeValueAsString(resultJson));
    }
}
